package com.hm.health.records;

import android.util.Log;

import androidx.annotation.NonNull;

import com.goodix.callback.AbsOnHBDTestClientListener;
import com.goodix.libromablecom.sdk.cardiff.CardiffConstants;
import com.goodix.comsdk.entity.MeasureResult;
import com.goodix.comsdk.sdk.OnHBDDataListener;
import com.goodix.comsdk.testsdk.IHBDTestClient;
import com.goodix.libromablecom.sdk.cardiff.arguments.StartArgumentsKeyEnum;
import com.hm.health.entity.arguments.StartArgumentsManager;

import java.util.concurrent.atomic.AtomicInteger;


/**
 * 丢包统计, 每次调用Start()方法，BLE设备端的数据包会重新计数
 * Created by chenshi on 2019/1/15.
 */

public class LostPacketStatistics {

    public static final String TAG = LostPacketStatistics.class.getSimpleName();

    // 包总数
    private int mTotalPackets;
    // 丢失包个数
    private int mLostPacketCount;
    // 上一个包序号
    private int mLastPackageIndex = -1;
    // 丢包统计状态
    private AtomicInteger mState = new AtomicInteger(StateEnum.STOPPED.ordinal());
    // 最大包序号
    private int mMaxPacketsIndex = 15;
    // SDK 接口
    private IHBDTestClient mHbdTestClient;

    enum StateEnum {
        STOPPED, STARTED, DETECTING
    }

    public void init(IHBDTestClient ihbdTestClient, int maxPacketsIndex) {
        mHbdTestClient = ihbdTestClient;
        mMaxPacketsIndex = maxPacketsIndex;
    }

    public void startDetection() {
        mTotalPackets = 0;
        mLostPacketCount = 0;
        mLastPackageIndex = -1;
        mState.set(StateEnum.STOPPED.ordinal());
        if(null != mHbdTestClient) {
            mHbdTestClient.registerHBDDataListener(mOnHBDDataListener);
            mHbdTestClient.registerCallback(mOnHBDTestClientListener);
        }
    }

    public void stopDetection() {
        if(null != mHbdTestClient) {
            mHbdTestClient.unRegisterHBDDataListener(mOnHBDDataListener);
            mHbdTestClient.unRegisterCallback(mOnHBDTestClientListener);
        }
    }

    /**
     * 检查是否丢包
     * @param nPackageIndex 原始数据包序号
     * @return  false: 未丢包， true: 丢包
     */
    private boolean isLostPackets(@NonNull int nPackageIndex) {

        if (mMaxPacketsIndex < nPackageIndex) {
            // 越界只取低4位
            nPackageIndex = nPackageIndex & 0xf;
        }

        boolean bContinous = false;
        int idRange = mMaxPacketsIndex + 1;
        if (mState.get() == StateEnum.DETECTING.ordinal()) {
            int dropNum = (nPackageIndex + idRange - mLastPackageIndex - 1) % idRange;
            if ((dropNum != 0) && (mLastPackageIndex != -1)) {
                bContinous = true;
                mLostPacketCount += dropNum;
                Log.d("LostPacketStatistics", "dropNum: " + dropNum);
                Log.d(TAG, String.format("isLostPackets: %d, %d", mLastPackageIndex, nPackageIndex));
                Log.d(TAG, "isLostPackets" +
                        "\tpackeNo: " + nPackageIndex
                        + "\tTotalPackageCount:" + mTotalPackets
                        + "\tlostPacketsCount: " + mLostPacketCount);
            }
        } else if (mState.compareAndSet(StateEnum.STARTED.ordinal(), StateEnum.DETECTING.ordinal())) {

        }
        mTotalPackets += 1;
        mLastPackageIndex = nPackageIndex;
        return bContinous;
    }

    /**
     * 原始数据接收
     */
    private OnHBDDataListener mOnHBDDataListener = new OnHBDDataListener() {
        @Override
        public void onDataChanged(String dataType, int[] dataArr) {

            String functionName = StartArgumentsManager.getInstance().getFunctionName();
            if (functionName.equals(dataType)) {
                if (functionName.equals(StartArgumentsKeyEnum.AppFunction_ECG)) {
                    int flag2 = dataArr[CardiffConstants.RawdataColumn.FLAG2.ordinal()] & 2;
                    if (2 == flag2) {
                        mLastPackageIndex = -1;
                    }
                }
                isLostPackets(dataArr[CardiffConstants.RawdataColumn.FRAME_ID.ordinal()]);
            }
        }

        @Override
        public void onMeasureResult(MeasureResult result) {

        }
    };

    /**
     * SDK 事件监听，若接收到了停止指令后则下一个接收的包不做丢包统计
     */
    private AbsOnHBDTestClientListener mOnHBDTestClientListener = new AbsOnHBDTestClientListener() {
        @Override
        public void onHBDStarted(int errCode) {
            super.onHBDStarted(errCode);
            Log.d(TAG, "onHBDStarted: ");
            mState.set(StateEnum.STARTED.ordinal());
        }

        @Override
        public void onHBDStopped(int errCode) {
            super.onHBDStopped(errCode);
            Log.d(TAG, "onHBDStopped: ");
            mState.set(StateEnum.STOPPED.ordinal());
        }

        @Override
        public void onDisconnected(int errCode) {
            Log.d(TAG, "onDisconnected: ");
            mState.set(StateEnum.STOPPED.ordinal());
        }
    };

    public int getTotalPackets() {
        return mTotalPackets + mLostPacketCount;
    }

    public int getLostPacketCount() {
        return mLostPacketCount;
    }
}
